<script setup lang="tsx">
import { computed, defineEmits, defineProps, nextTick, provide, ref, watch } from 'vue';
import { UUID } from 'uuidjs';
import useDragModal from '@/hooks/common/dragModal';
import { useAppStore } from '@/store/modules/app';

interface Props {
  title?: any;
  width?: string;
  height?: string;
  wrapClassName?: string;
  wrapStyle?: any;
  mask?: boolean;
  destroyOnClose?: boolean;
  centered?: boolean;
  showResetBtn?: boolean;
  showConfirmBtn?: boolean;
  confirmBtnText?: string;
  cancelBtnText?: string;
  showCancelBtn?: boolean;
  showFooter?: boolean;
  visible: any;
  loading?: any;
}

interface Emits {
  (e: 'close', isClear: boolean): void;
  (e: 'reset'): void;
  (e: 'ok'): void;
}

const emit = defineEmits<Emits>();
const full = ref(false);

const appStore = useAppStore();

const props = withDefaults(defineProps<Props>(), {
  title: '',
  width: '800px',
  height: 'auto',
  wrapClassName: '',
  wrapStyle: {},
  showConfirmBtn: true,
  showCancelBtn: true,
  showFooter: true,
  confirmBtnText: '确定',
  cancelBtnText: '取消',
  loading: false,
  mask: false,
  destroyOnClose: false,
  centered: false,
  showResetBtn: false
});
const visible = ref(props.visible);
const loading = ref(props.loading);
watch(
  () => props.visible,
  val => {
    visible.value = val;
  }
);

watch(
  () => props.loading,
  val => {
    loading.value = val;
  }
);

const contentRef = ref(null);

// 记录对话框关闭时候的大小
const closeWidth = ref<null | string>(null);
const closeHeight = ref<null | string>(null);

const width: any = ref<string>(props.width || '800px');
const height: any = ref<string>(props.height || 'auto');

// 弹窗样式
const wrapStyle = computed(() => {
  let obj = {
    overflow: 'hidden'
  };
  if (props?.wrapStyle) {
    obj = {
      ...obj,
      ...props?.wrapStyle
    };
  }
  return obj;
});

const modalUUid = UUID.genV4().hexNoDelim;

// 弹窗类名
const wrapClassName = computed(() => {
  let str = `jv-modal modal-${modalUUid} ${full.value ? '' : 'not-full-modal'}`;
  if (props?.wrapClassName) {
    str += ` ${props?.wrapClassName}`;
  }
  return str;
});

const modalTitleRef: any = ref(null);
const transformStyle: any = ref(useDragModal(modalTitleRef));
function observerModalContent() {
  if (!visible.value || full.value) return;
  nextTick(() => {
    const selecttor = `.modal-${modalUUid} .ant-modal-content`;
    const element: Element = document.querySelector(selecttor) as any;
    const resizeObserver = new ResizeObserver(entries => {
      for (const entry of entries) {
        const contentRectWidth = entry.contentRect.width;
        const contentRectHeight = entry.contentRect.height;
        width.value = `${contentRectWidth}px`;
        height.value = `${contentRectHeight}px`;
      }
      transformStyle.value = useDragModal(modalTitleRef);
    });
    resizeObserver.observe(element);
  });
}

watch(visible, () => {
  if (visible.value) {
    width.value = closeWidth.value || props.width;
    height.value = closeHeight.value || props.height;
    observerModalContent();
  }
});

function close(isClear: boolean = false) {
  visible.value = false;
  closeWidth.value = width.value;
  closeHeight.value = height.value;
  emit('close', isClear);
}

function onOk(cb = () => {}) {
  emit('ok');
  cb && cb();
}

provide('ok', () => {
  onOk();
});

provide('close', (isClear: boolean) => {
  close(isClear);
});
provide('reset', onReset);

function onReset(cb = () => {}) {
  emit('reset');
  cb && cb();
}

function parseTranslate(translateStr: any) {
  const str = translateStr
    .replace('translate', '')
    .trim()
    .replace(')', '')
    .replace('(', '')
    .replace(/px/g, '')
    .split(',');
  return {
    x: Number(str[0]),
    y: Number(str[1])
  };
}

const modalContentRef = ref(null);
const fullStyle = ref({});

function handleFull() {
  full.value = !full.value;
  nextTick(() => {
    const position = parseTranslate(transformStyle.value.transform);
    if (full.value) {
      width.value = `${window.innerWidth}px`;
      height.value = `${window.innerHeight}px`;

      const titleRect = modalTitleRef.value.getBoundingClientRect();
      const asideWidth = appStore.siderCollapse ? 64 : 220;
      const x = Math.min(Math.max(titleRect.left, titleRect.x), titleRect.right) - asideWidth;
      let y = 0 - titleRect.height;
      if (props.centered) {
        y = 29;
      }
      fullStyle.value = {
        width: `${window.innerWidth - asideWidth}px`,
        height: `${window.innerHeight - 56}px`,
        transform: `translate(${-x + position.x}px, ${y}px)`
      };
    } else {
      width.value = props.width;
      height.value = props.height;
      fullStyle.value = {};
      observerModalContent();
    }
  });
}
</script>

<template>
  <AModal
    v-model:open="visible"
    :width="props.width"
    :wrap-class-name="wrapClassName"
    :wrap-style="wrapStyle"
    :mask="props.mask"
    :destroy-on-close="props.destroyOnClose"
    :centered="props.centered"
    :after-close="close"
    @close="close"
  >
    <template #title>
      <div ref="modalTitleRef" class="modal-title w-full flex" :class="full ? '' : 'cursor-move select-none'">
        <slot name="title">
          <div class="title">{{ props.title }}</div>
        </slot>
        <div class="close-btn flex-center">
          <AButton type="link" class="mr-10px pr-0" @click="close(false)">
            <icon-ic-round-minus class="close-icon text-icon" />
          </AButton>
          <AButton type="link" class="mr-10px pl-0 pr-0" @click="handleFull">
            <span class="icon iconfont color-#fff" :class="full ? 'icon-tuichuquanping' : 'icon-quanping'"></span>
          </AButton>

          <AButton type="link" class="pl-0" @click="close(true)">
            <icon-ic-round-close class="close-icon text-icon" />
          </AButton>
        </div>
      </div>
    </template>
    <template #modalRender="{ originVNode }">
      <component
        :is="originVNode"
        ref="modalContentRef"
        :style="{
          ...transformStyle,
          height: height,
          width: width,
          ...fullStyle
        }"
      />
      <!-- </div> -->
    </template>
    <div ref="contentRef" class="modal-content-warp">
      <slot></slot>
    </div>
    <template v-if="props.showFooter" #footer>
      <slot name="footer">
        <div class="modal-footer">
          <!-- 重置按钮 -->
          <AButton v-if="props.showResetBtn" @click="onReset()">重置</AButton>
          <!-- 确定按钮 -->
          <AButton v-if="props.showConfirmBtn" type="primary" :loading="loading" @click="onOk()">
            {{ props.confirmBtnText }}
          </AButton>
          <!-- 取消按钮 -->
          <AButton v-if="props.showCancelBtn" @click="close(true)">{{ props.cancelBtnText }}</AButton>
        </div>
      </slot>
    </template>
  </AModal>
</template>

<style lang="scss">
.jv-modal {
  .modal-title {
    color: #fff;
    text-align: center;
    position: relative;
    background: #5F9EA0;
    line-height: 44px;
    font-weight: bold;

    .title {
      width: calc(100% - 140px);
      padding-left: 120px;
      margin-left: 20px;
      // 文本溢出隐藏
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .close-btn {
      position: absolute;
      top: 5px;
      right: 0;

      .ant-btn-link {
        color: #fff;

        .close-icon {
          font-size: 24px;
        }
      }
    }
  }

  .modal-content {
    width: auto;
    height: 100%;
  }
  .ant-modal-content {
    overflow: auto;
    padding: 0;
  }

  &.not-full-modal {
    .ant-modal-content {
      resize: both;
    }
  }

  .ant-modal-body {
    height: calc(100% - 108px);
    overflow: auto;
  }

  .modal-content-warp {
    $color: rgba(0, 0, 0, 0.5);
    $size: 7px;
    overflow: auto;
    padding: 15px;
    height: 100%;
    scrollbar-width: thin;
    scrollbar-color: $color #e4e3e3;

    /* 设置滚动条颜色 */
    ::-webkit-scrollbar-track {
      background-color: #eee;
    }

    &::-webkit-scrollbar-thumb {
      background-color: $color;
      border-radius: $size;
    }

    &::-webkit-scrollbar-thumb:hover {
      background-color: $color;
      border-radius: $size;
    }

    &::-webkit-scrollbar {
      width: $size;
      height: $size;
    }

    &::-webkit-scrollbar-track-piece {
      background-color: rgba(0, 0, 0, 0);
      border-radius: 0;
    }

    &::-webkit-scrollbar-track {
      background-color: #f0f0f0;
      /* 滚动条轨道颜色 */
    }
  }

  .ant-modal-close {
    display: none;
  }

  .ant-modal-footer {
    height: 44px;
    line-height: 44px;
    background-color: #dfe2ea;

    .modal-footer {
      text-align: center;
    }
  }
}
</style>
